/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2025. All rights reserved.
 *
 */

import { CoreTask, TaskDetails } from '@ohos/hvigor';

import { ApiVersion } from '../../const/sdk-const.js';
import { CodeType } from '../../enum/code-type-enum.js';
import { ModuleType } from '../../enum/module-type-enum.js';
import { HarTargetUtil } from '../../utils/har-target-util.js';
import { declareReloadDepends, limitMinApiVersion } from '../../utils/task-util.js';
import { ArkCompile } from '../ark-compile.js';
import { ColdReloadArkCompile } from '../cold-reload-ark-compile.js';
import { TaskNames } from '../common/task-names.js';
import { CompileNode } from '../compile-node.js';
import { CompileResource } from '../compile-resource.js';
import { GenerateLoaderJson } from '../generate-loader-json.js';
import { HarArkCompile } from '../har/har-ark-compile.js';
import { HarCompileNode } from '../har/har-compile-node.js';
import { HotReloadArkCompile } from '../hot-reload-ark-compile.js';
import { OhosTestArkCompile } from '../ohosTest/ohos-test-ark-compile.js';
import { OhosTestCompileNode } from '../ohosTest/ohos-test-compile-node.js';
import { PreviewerArkCompile } from '../previewer-ark-compile.js';
import { TargetTaskService } from '../service/target-task-service.js';
import { TargetTaskCreator, TaskCreatorManager } from '../task-creator.js';
import { UnitTestArkCompile } from '../unitTest/unit-test-ark-compile.js';

import CommonTask = TaskNames.CommonTask;

export const initializeArkTsTasks = (service: TargetTaskService, creatorManager: TaskCreatorManager) => {
  // compile
  const moduleType = service.getModuleService().getModuleModel().getModuleType();
  if (moduleType === ModuleType.Har) {
    creatorManager.registry(new ArkTsHarTaskCA(service, CodeType.ETS));
    creatorManager.registry(new NodeHarBuildTaskCA(service, CodeType.ETS));
    creatorManager.registry(new ArkTsTaskCA(service, CodeType.ETS));
    creatorManager.registry(new NodeBuildTaskCA(service, CodeType.ETS));
    creatorManager.registry(new NodeBuildTaskCA(service, CodeType.JS));
  } else {
    creatorManager.registry(new ArkTsTaskCA(service, CodeType.ETS));
    creatorManager.registry(new ArkTsTaskCA(service, CodeType.JS));
    creatorManager.registry(new NodeBuildTaskCA(service, CodeType.ETS));
    creatorManager.registry(new NodeBuildTaskCA(service, CodeType.JS));
  }

  // hotreload
  creatorManager.registry(new ArkTsHotReloadCA(service, CodeType.ETS));

  // coldreload
  creatorManager.registry(new ArkTsColdReloadCA(service, CodeType.ETS));

  // preview
  creatorManager.registry(new ArkTsPreviewCA(service, CodeType.ETS));

  // test
  creatorManager.registry(new ArkTsOhosTestCA(service, CodeType.ETS));
  creatorManager.registry(new ArkTsOhosTestCA(service, CodeType.JS));
  creatorManager.registry(new NodeOhosTestBuildTaskCA(service, CodeType.ETS));
  creatorManager.registry(new NodeOhosTestBuildTaskCA(service, CodeType.JS));
  creatorManager.registry(new ArkTsUnitTestCA(service, CodeType.ETS));
};

export class ArkTsTaskCA extends TargetTaskCreator {
  protected codeType: CodeType;

  constructor(taskService: TargetTaskService, codeType: CodeType) {
    super(taskService);
    this.codeType = codeType;
  }

  provider = (): CoreTask => new ArkCompile(this.targetService, this.codeType, TaskNames.Task.COMPILE_ARK);

  declareTaskDetail = () => getLangCompileTaskName(this.codeType, TaskNames.Task.COMPILE_ARK);

  declareDepends = (): string[] => {
    const depends: string[] = [GenerateLoaderJson.name, CompileResource.name].concat(getBuildProfileDependence(this.targetService));
    return depends;
  };
}

export class ArkTsHarTaskCA extends ArkTsTaskCA {
  provider = (): CoreTask => new HarArkCompile(this.targetService, this.codeType, TaskNames.Task.HAR_COMPILE);

  declareTaskDetail = () => getLangCompileTaskName(this.codeType, TaskNames.Task.HAR_COMPILE);
  declareDepends = () => {
    if (limitMinApiVersion(this.targetService.getTargetData(), ApiVersion.API_VERSION_9)) {
      return [GenerateLoaderJson.name, CompileResource.name, CommonTask.CREATE_HAR_BUILD_PROFILE.name];
    }
    return [GenerateLoaderJson.name, CompileResource.name];
  };
}

export class ArkTsOhosTestCA extends ArkTsTaskCA {
  provider = (): CoreTask => new OhosTestArkCompile(this.targetService, this.codeType);

  declareTaskDetail = () => getLangCompileTaskName(this.codeType, TaskNames.Task.OHOS_TEST_ARK_COMPILE);
}

export class ArkTsUnitTestCA extends ArkTsTaskCA {
  provider = (): CoreTask => new UnitTestArkCompile(this.targetService, this.codeType, TaskNames.Task.UNIT_TEST);

  declareTaskDetail = () => getLangCompileTaskName(this.codeType, TaskNames.Task.UNIT_TEST);

  declareDepends = (): string[] => {
    const depends: string[] = [TaskNames.Task.BUILD_UNIT_TEST_RES.name, TaskNames.CommonTask.UNIT_TEST_PROCESS_PROFILE.name].concat(
      getBuildProfileDependence(this.targetService),
    );
    return depends;
  };
}

export class ArkTsPreviewCA extends ArkTsTaskCA {
  provider = (): CoreTask => new PreviewerArkCompile(this.targetService, this.codeType, TaskNames.Task.PREVIEW);

  declareTaskDetail = () => getLangCompileTaskName(this.codeType, TaskNames.Task.PREVIEW);

  declareDepends = (): string[] => {
    const depends = [TaskNames.Task.PREVIEW_UPDATE_ASSETS.name];
    if (limitMinApiVersion(this.targetService.getTargetData(), ApiVersion.API_VERSION_9)) {
      depends.push(TaskNames.CommonTask.CREATE_BUILD_PROFILE.name);
    }
    return depends;
  };
}

export class ArkTsHotReloadCA extends ArkTsTaskCA {
  provider = (): CoreTask => new HotReloadArkCompile(this.targetService, this.codeType, TaskNames.Task.HOT_RELOAD);

  declareTaskDetail = () => getLangCompileTaskName(this.codeType, TaskNames.Task.HOT_RELOAD);

  declareDepends = () => {
    return declareReloadDepends(this.targetService);
  };

  afterConfigure = () => {
    this.depends = this.declareDepends().map((depend) => (depend.includes(':') ? depend : `${this.node.getName()}:${depend}`));
  };
}

export class ArkTsColdReloadCA extends ArkTsTaskCA {
  provider = (): CoreTask => new ColdReloadArkCompile(this.targetService, this.codeType, TaskNames.Task.COLD_RELOAD);

  declareTaskDetail = () => getLangCompileTaskName(this.codeType, TaskNames.Task.COLD_RELOAD);

  declareDepends = () => {
    return [];
  };
}

export class NodeBuildTaskCA extends ArkTsTaskCA {
  provider = (): CoreTask => new CompileNode(this.targetService, this.codeType, TaskNames.Task.COMPILE_NODE);

  declareTaskDetail = () => getLangCompileTaskName(this.codeType, TaskNames.Task.COMPILE_NODE);

  declareDepends = () => [GenerateLoaderJson.name, CompileResource.name];
}

export class NodeHarBuildTaskCA extends NodeBuildTaskCA {
  provider = (): CoreTask => new HarCompileNode(this.targetService, this.codeType, TaskNames.Task.HAR_BUILD);

  declareTaskDetail = () => getLangCompileTaskName(this.codeType, TaskNames.Task.HAR_BUILD);
}

export class NodeOhosTestBuildTaskCA extends ArkTsTaskCA {
  provider = (): CoreTask => new OhosTestCompileNode(this.targetService, this.codeType);

  declareTaskDetail = () => getLangCompileTaskName(this.codeType, TaskNames.Task.OHOS_TEST_COMPILE_NODE);
}

const getLangCompileTaskName = (codeType: CodeType, details: TaskDetails): TaskDetails => {
  return { ...details, name: `${details.name}${codeType === CodeType.ETS ? 'ArkTS' : codeType.toUpperCase()}` };
};

const getBuildProfileDependence = (targetService: TargetTaskService) => {
  const depends: string[] = [];
  const apiGreaterThan9 = limitMinApiVersion(targetService.getTargetData(), ApiVersion.API_VERSION_9);
  if (apiGreaterThan9) {
    depends.push(CommonTask.CREATE_BUILD_PROFILE.name);

    // 如果hap/hsp引用了本地har模块则额外调用har模块的CREATE_HAR_BUILD_PROFILE任务用于生成BuildProfile.ets文件
    const depHarTargets = HarTargetUtil.calDepHarTargets(targetService);
    depHarTargets.forEach((targetName, harName) => depends.push(`${harName}:${targetName}@${CommonTask.CREATE_HAR_BUILD_PROFILE.name}`));
  }
  return depends;
};
